;====================
;AHK REAPER FUNCTIONS
;====================

ClearRenderQueue()
{
	queueDir = %A_AppData%\REAPER\QueuedRenders
	FileDelete, %queueDir%\*
}

AddToRenderQueue( StartTime, EndTime, TrackNum, Filename )
{
	global RPP
	
	SplitPath, RPP, rppFilename
	queueDir = %A_AppData%\REAPER\QueuedRenders
	
	renderTimestamp := Timestamp(3)
	;renderQueueFile = render_%renderTimestamp%_%rppFilename%
	renderQueueFile = render_autorender_%TrackNum%.rpp
	FileRead, rppFile, %RPP%

	targetRenderFileRegex := "RENDER_FILE.*\R"
	renderFile = RENDER_FILE "%Filename%"`r
	rppFile := RegExReplace(rppFile, targetRenderFileRegex, renderFile )

	targetRenderRangeRegex := "RENDER_RANGE.*\R"
	renderRange = RENDER_RANGE 0 %StartTime% %EndTime%`r	  
	rppFile := RegExReplace(rppFile, targetRenderRangeRegex, renderRange)

	FileDelete, %queueDir%\%renderQueueFile%
	FileAppend, %rppFile%, %queueDir%\%renderQueueFile%
	;MsgBox %queueDir%\%renderQueueFile% written
}

GetUserVars(RPP)
{
	global
	local tmpInNotes, curNoteLine, curNoteLineArray0, tmpUserVarName, tmpUserVarValue

	;=== How the output vars work
	;=== UserVarCount is the number of project notes variables that were found. The arrays use this as their index,
	;===  so you can Loop %ProjectNotesVarCount% and then call array values like UserVar%A_Index%Name
	;=== UserVar*Name is the name of the variable
	;=== UserVar*Value is the name of the variable

	UserVarCount = 0

	;=== Loop through all the lines in the project file...
	Loop, Read, %RPP%
	{
		;=== Look for the end of the notes section
	    If (tmpInNotes AND RegExMatch(A_LoopReadLine, "^  >"))
	    {
	        tmpInNotes = 0
	    }

		;=== This is a variable in the notes, read it
	    If (tmpInNotes AND InStr(A_LoopReadLine, "="))
	    {
	        curNoteLine := RegExReplace(A_LoopReadLine, "^(\s|\|)*","","all")
			UserVarCount += 1
			UserVar%UserVarCount%Name := TrimWhitespace( SubStr( curNoteLine, 1, InStr(curNoteLine, "=")-1  ) )
	        UserVar%UserVarCount%Value := TrimWhitespace( SubStr( curNoteLine, InStr(curNoteLine,"=")+1 ) )
			
			;==Debug
			;MsgBox % UserVar%UserVarCount%Name
			;MsgBox % UserVar%UserVarCount%Value
		}

		;=== We're now in the notes, set the variable
	    If RegExMatch(A_LoopReadLine, "^  <NOTES ")
	    {
	        tmpInNotes = 1
	    }
	}
}

GetRegions(RPP)
{
	global
	local curMarkerSection0, curRegionData0, tmpMarkerData, tmpMarkerName, tmpMarkerType, tmpMarkerTime, tmpMarkerID, tmpRegionStartFound, tmpIllegalFilenameCharRegex, thisLine
	
	;=== How the output vars work
	;=== RegionCount is the number of regions that were found. All the arrays use this as their index,
	;===  so you can Loop %RegionCount% and then call array values like Region%A_Index%_MarkerID	
	;=== Region*_MarkerID is an array of the regions Reaper marker IDs
	;=== Region*_StartTime is the start time of the region (decimal seconds)
	;=== Region*_StartTimeMinSec is the start time of the region (Minutes:Seconds)
	;=== Region*_EndTime is the end time of the region (decimal seconds)
	;=== Region*_EndTimeMinSec is the end time of the region (Minutes:Seconds)
	;=== Region*_Name is the region name
	
	;=== Loop through all the lines in the project file...
	Loop, Read, %RPP%
	{
		;=== Look for markers
	    If RegExMatch(A_LoopReadLine, "^  MARKER ")
	    {				    
			;=== tmpMarkerID = Reaper's Marker ID
			;=== tmpMarkerTime = Time (decimal seconds)
			;=== tmpMarkerName = The marker name
			;=== tmpMarkerType = The marker type (0 for normal, 1 for region boundary)
	    
	    	thisLine = %A_LoopReadLine% ;AUTOTRIM IT!
	    	StringSplit,curMarkerSection,thisLine,%A_Space%%A_Tab%
	    	tmpMarkerName := ""
	    	Loop %curMarkerSection0%
	    	{
				If A_Index = 1
				{
					;MARKER					
				}
				Else If A_Index = 2
				{
					;MARKER ID
					tmpMarkerID := curMarkerSection%A_Index%
				}
				Else If A_Index = 3
				{
					;TIME	
					tmpMarkerTime := curMarkerSection%A_Index% + ProjectOffset
				}
				Else If A_Index = %curMarkerSection0%
				{
					;TYPE
					tmpMarkerType := curMarkerSection%A_Index%
				}
				Else
				{
					;PART OF MARKER NAME
					If StrLen( tmpMarkerName ) = 0
					{
						tmpMarkerName := curMarkerSection%A_Index%
					}
					Else
					{
						tmpMarkerData := curMarkerSection%A_Index%
						tmpMarkerName = %tmpMarkerName% %tmpMarkerData%
					}
					
				}
	    	}
	    	
	    	;REMOVE QUOTES FROM MARKER NAME
	    	StringTrimLeft, tmpMarkerName, tmpMarkerName, 1
			StringTrimRight, tmpMarkerName, tmpMarkerName, 1
	    	
	    	;MsgBox %tmpMarkerID%
	    	;MsgBox %tmpMarkerTime%
	    	;MsgBox %tmpMarkerType%
	    	;MsgBox %tmpMarkerName%

			; === Is this is a region boundary?
			If tmpMarkerType = 1
	        {								
				
				;=== This will be set to 1 if we determine that this is the end marker of the region
				tmpRegionStartFound = 0
								
				;=== Check if we already have the start marker for this region
	            
				Loop %RegionCount%
				{																											
					If (Region%A_Index%_MarkerID = tmpMarkerID)
					{										
						;=== This is the end marker of the region (Start marker for this region has already been found)
		                tmpRegionStartFound = 1
						Region%A_Index%_EndTime := tmpMarkerTime
						Region%A_Index%_EndTimeMinSec := TimeToMinSec(tmpMarkerTime)						
						
					}
				}

				If tmpRegionStartFound = 0
	            {
	                ;=== This is the start marker of a region
					RegionCount += 1	                
					Region%RegionCount%_MarkerID := tmpMarkerID
	                Region%RegionCount%_StartTime := tmpMarkerTime
					Region%RegionCount%_StartTimeMinSec := TimeToMinSec(tmpMarkerTime)
					 
					SetRegionName(RegionCount, tmpMarkerName) 								
	            }    
	        }
	    }
	}
}

TimeToMinSec(Time)
{
	If time >= 0 
	{
		minute := floor(Time/60)
	}
	Else
	{
		minute := ceil(Time/60)
	}
	seconds := mod(Time, 60)
	minsec := minute . ":" . seconds
	Return minsec
}

GetProjectOffset(RPP)
{
	Loop, Read, %RPP%
	{
		;=== Look for markers
	    If RegExMatch(A_LoopReadLine, "^  PROJOFFS ")
	    {	
			projectOffsetLine = %A_LoopReadLine%
			StringSplit,projectOffsetArray,projectOffsetLine,%A_Space%,%A_Space%%A_Tab%
			Return projectOffsetArray2
		}
	}
	
}

SetRegionName(RegionNumber, Name)
{
	global
	local IllegalFilenameCharRegex
	
	If !Name
	{
		Region%RegionNumber%_Name := "Untitled"
	}
	Else
	{
		;Region%RegionNumber%_Name := RegExReplace(Name, "(^""|^'|^``|``$|'$|""$)")
		Region%RegionNumber%_Name := Name
	}

	If !IllegalFilenameCharRegex
	{
		IllegalFilenameCharRegex = (\\|/|:|\*|\?|"|<|>|\|)
	}
	
	Region%RegionNumber%_Filename := RegExReplace(Region%RegionNumber%_Name, IllegalFilenameCharRegex, "_")
	Return
}

MakeFilenamesUnique()
{
	global
	local rNum, uniqueFilename, thisFilename, curFilename, uniqueCounter, thisUniqueFilename
	
	Loop %RegionCount%
	{
		rNum := A_Index
		thisFilename := Region%rNum%_Filename
		thisUniqueFilename := thisFilename
		uniqueCounter = 1
		
		Loop
		{
			uniqueFilename = 1
			Loop %RegionCount%
			{
				If( rNum > A_Index )
				{
					curFilename := Region%A_Index%_Filename
					
					If( curFilename = thisUniqueFilename)
					{
						uniqueFilename = 0
					}		
				}
			}

			If uniqueFilename = 1
			{
				Break
			}		
			Else
			{
				uniqueCounter++		
				thisUniqueFilename = %thisFilename% %uniqueCounter%				
			}
		}
		If thisFilename != thisUniqueFilename
		{
			Region%rNum%_Filename := thisUniqueFilename
		}
	}
}

GetReaperIni()
{	
	; === Try to get the ini file and  find out what the most recent project is (i.e. the currently open project)			
	; === Find the .ini file
	
	; === First try Autorender.ini
	IniRead, ReaperIni, Autorender.ini, Autorender, ReaperIni
	
	If !FileExist(ReaperIni)
	{
		;=== Recurse up through directories looking for Reaper.ini (for USB and other "non-installations"
		recurseDir = %A_WorkingDir%\
		Loop
		{
			If InStr(recurseDir, "\")
			{
				recurseDir := RegExReplace(recurseDir, "\\([^\\]*?)$")							
				If FileExist(recurseDir . "\REAPER.ini")
				{
					ReaperIni = %recurseDir%\REAPER.ini
					Break
				}
			}
			Else
			{
				Break
			}	
		}

		If !FileExist(ReaperIni)
		{
			If FileExist(A_AppData . "\REAPER\REAPER.ini")
			{
				; === "Installed" ini files
				ReaperIni = %A_AppData%\REAPER\REAPER.ini
			}
		}

		If !FileExist(ReaperIni)
		{
			MsgBox,262164,Couldn't find Reaper.ini,Autorender couldn't find Reaper.ini. Do you want to manually select its location?
			IfMsgBox Yes
			{
				FileSelectFile,Reaperini,1,,Select Reaper.ini,*.ini
			}		
		}
		If FileExist(ReaperIni)
		{
			;We couldn't read it from Autorender.ini before, so write it now
			IniWrite, %ReaperIni%, Autorender.ini, Autorender, ReaperIni
		}
	}
	Return ReaperIni
}
	
GetRPP(ReaperIni)	
{
	; === If we found the ini file, grab the most recent project
	If FileExist(ReaperIni)
	{
	    IniRead, recentNum, %ReaperIni%, REAPER, numrecent

	    If recentNum < 10
	    {
	        recentNum = 0%recentNum%
	    }

	    IniRead, RPP, %ReaperIni%, Recent, recent%recentNum%
	}
	
	If !FileExist(RPP)
	{
		; === If we didn't find the ini file, just ask the user
		TrayTip, Autorender, Autorender couldn't figure out where the current project's .rpp file is. Please select it with the file selector..., 5, 2
	  	FileSelectFile,RPP,1,,Select Currently Reaper Project File,*.rpp
	}
	Return RPP
}


StrPad(stringVar, padLength = 2, padChar = 0, padDirection = 1)
{
	If !padLength
	{
		padLength = 2
	}
	
	If !padChar
	{
		padChar = 0
	}
	
	Loop	
	{
		If ( StrLen(stringVar) < padLength )
		{
			If (padDirection = 2)
			{
				stringVar = %stringVar%%padChar%
			}
			If (padDirection = 3)
			{
				If Mod(A_Index,2)
				{
					stringVar = %stringVar%%padChar%
				}
				Else
				{
					stringVar = %padChar%%stringVar%
				}
			}
			Else
			{
				stringVar = %padChar%%stringVar%
			}
			
		}
		Else
		{
			Break
		}
	}
	Return stringVar
}

Timestamp(timeFormat=1)
{
	If timeFormat = 2
	{
		FormatTime, curTime, , yyyyMMddHHmmss
	}
	Else If timeFormat = 3
	{
		FormatTime, curTime, , yyMMdd_HHmmss
	}
	Else
	{
		FormatTime, curTime, , yyyy-MM-dd HH:mm:ss	
	}
	Return curTime
}

GetRenderFormat()
{
	global rcComboBoxOutputFormat
	
	IfWinNotExist,Render to file
	{	
		;=== Open render dialog
		PostMessage,0x111,40015            
	    	WinWait,Render to file
		launchedRenderWindow = 1
	}
	
	;===Find out if we're rendering mp3s, so we can tag later
	ControlGetText,renderFormatText,%rcComboBoxOutputFormat%
	
	If RegExMatch(renderFormatText,"i)^\.WAV")
	{
		renderFormat = wav
	}
	Else If RegExMatch(renderFormatText,"i)^AIFF")
	{
		renderFormat = aiff
	}	
	Else If RegExMatch(renderFormatText,"i)^Monkey")
	{
		renderFormat = monkey
	}
	Else If RegExMatch(renderFormatText,"i)^Audio CD Image")
	{
		renderFormat = cdimage
	}		
	Else If RegExMatch(renderFormatText,"i)^FLAC")
	{
		renderFormat = flac
	}			
	Else If RegExMatch(renderFormatText,"i)^MP3")
	{
		renderFormat = mp3
	}
	Else If RegExMatch(renderFormatText,"i)^OGG")
	{
		renderFormat = ogg
	}
	Else If RegExMatch(renderFormatText,"i)^WavPack")
	{
		renderFormat = wavpack
	}				
	
	If launchedRenderWindow
	{
		PostMessage,0x111,2
		Sleep,500
		IfWinExist,Render to file
		{
			WinKill,Render to file
		}
	}

	Return renderFormat
}

GetRenderFormatExt(renderFormat)
{
	If (renderFormat = "wav")
	{
		renderFormatExt = wav
	}
	Else If (renderFormat = "aiff")
	{
		renderFormatExt = aif
	}	
	Else If (renderFormat = "monkey")
	{
		renderFormatExt = ape
	}
	Else If (renderFormat = "cdimage")
	{
		renderFormatExt = cue
	}		
	Else If (renderFormat = "flac")
	{
		renderFormatExt = flac
	}
	Else If (renderFormat = "mp3")
	{
		renderFormatExt = mp3
	}	
	Else If (renderFormat = "ogg")
	{
		renderFormatExt = ogg
	}	
	Else If (renderFormat = "wavpack")
	{
		renderFormatExt = wv
	}				
	Return renderFormatExt
}

CloseRenderWindows()
{
	global rcButtonCancel
	; === Close any render windows if they are already open
	Loop
	{
		IfWinExist,Render to file
		{
			WinActivate,Render to file
			WinWaitActive
			Control,Enable,,%rcButtonCancel%,Render to file		;Enable cancel button		
			WinClose,Render to file
		}
		Else IfWinExist,Rendering to file
		{
			PostMessage,0x111,2,,Rendering to file
			Sleep,500
			IfWinExist,Rendering to file
			{
				WinClose,Rendering to file
			}
		}
		Else IfWinExist,Queued Renders
		{
			WinKill,Queued Renders
		}		
		Else IfWinExist,REAPER Warning
		{
			WinClose,REAPER Warning
		}
		Else
		{
			Break
		}
	}
	Sleep 2000
}

GetReaperWindowID()
{	
	ReaperID := WinExist("REAPER v","",":\") 
	WinActivate, ahk_id %ReaperID%
	Return ReaperID
}

GetReaperVersion( ReaperID )
{
	WinGetTitle, ReaperWindowTitle, ahk_id %ReaperID%
	StringSplit,titleSplit,ReaperWindowTitle,%A_Space%								
	
	detectedReaperVersion =
	
	Loop %titleSplit0%
	{
		thisWord := titleSplit%A_Index%
		If ( SubStr( thisWord, 1, 1) = "v" )
		{
			detectedReaperVersion := SubStr( thisWord, 2)
		}
	}

	AppendLog("Reaper Version Detected: " . detectedReaperVersion)
	Return detectedReaperVersion
}

InitLog()
{
	FileDelete Autorender.log
}

AppendLog(Message="",NewSection=0)
{	
	If NewSection
	{
		Prespace = `n`n
		LogLine = `n----------------------------------------
	}

	If !Message
	{
		FileAppend,`n, Autorender.log	
	}
	Else
	{
		curTime := TimeStamp()
		FileAppend, %Prespace%`n[%curTime%] %Message%%LogLine%, Autorender.log
	}
}

ShowLog()
{
	Run Notepad Autorender.log
}

SetLoopRegion(starttime, endtime)
{
	global ReaperID
	
	WinActivate, ahk_id %ReaperID%
	WinWaitActive,ahk_id %ReaperID%
	PostMessage,0x111,40020,,,ahk_id %ReaperID%            ;Escape
	PostMessage,0x111,40069,,,ahk_id %ReaperID%            ;Open jump dialog

	WinWait,Jump
	ControlSetText,Edit1,%starttime%,Jump
	ControlClick,Button1,Jump
	WinWaitClose,Jump
	WinActivate, ahk_id %ReaperID%
	WinWaitActive,ahk_id %ReaperID%

	PostMessage,0x111,40222,,,ahk_id %ReaperID%            ;Set region start
	PostMessage,0x111,40069,,,ahk_id %ReaperID%            ;Open jump dialog

	WinWait,Jump
	ControlSetText,Edit1,%endtime%
	ControlClick,Button1
	WinWaitClose,Jump
	WinActivate, ahk_id %ReaperID%
	WinWaitActive,ahk_id %ReaperID%
			
	PostMessage,0x111,40223,,,ahk_id %ReaperID%          ;Set region end
}

TrimWhitespace(targetString)
{
	targetString := RegExReplace(targetString, "^\s*", "", "all")
	targetString := RegExReplace(targetString, "\s*$", "", "all")
	Return targetString
}

ShowFinishedGUI()
{
	global
	local FinishedGuiSubmitted
	
	Gui, 2:Add, Button,w150 xm r1,&Open Render Directory
	Gui, 2:Add, Button,w150 xp+150 r1,&Show Log
	Gui, 2:Add, Button,w150 xp+150 r1 Default,&Close
	Gui, 2:Show,,Autorender Complete

	Loop
	{
		Sleep, 1000
	}

	2ButtonOpenRenderDirectory:
	Run, %renderPath%
	Return
	
	2ButtonShowLog:
	ShowLog()
	Return
	
	2GuiEscape:
	2GuiClose:
	2ButtonClose:
	Gui, 2:Destroy
	ExitApp
	Return
}

ShowMetadataGUI()
{
	global	
	local inputWidth = 300, Submitted, TmpRegionName, curRegionName, LogVar, Col1Width = 100, listViewRows, SFolder, autoTrackPad

	Gui, Add, Text,xm r1,Artist:
	Gui, Add, Edit,vUserVar_Artist w%inputWidth% xp+%Col1Width% r1, %UserVar_Artist%  ; The ym option starts a new column of controls.
	
	Gui, Add, Text,xm r1,Album:
	Gui, Add, Edit, vUserVar_Album w%inputWidth% xp+%Col1Width% r1, %UserVar_Album%

	Gui, Add, Text,xm r1,Genre:
	Gui, Add, Edit, vUserVar_Genre w%inputWidth% xp+%Col1Width% r1, %UserVar_Genre%
	
	Gui, Add, Text,xm r1,Year:
	Gui, Add, Edit, vUserVar_Year w%inputWidth% xp+%Col1Width% r1, %UserVar_Year%	

	Gui, Add, Text,xm r1,Note: If you're not rendering to mp3, you can leave the above fields blank...

	Gui, Add, Text,xm yp+30 r1,Output Directory:		
	Gui, Add, Edit, section w250 vUserVar_RenderPath xp+%Col1Width% r1, %UserVar_RenderPath%
	Gui, Add, Button,xp+250 W50 r1, &Browse	
	
	Gui, Add, Text,xm yp+30 r1,Press F2 to edit track names

	If RegionCount > 20
	{
		listViewRows = 20
	}
	Else
	{
		listViewRows := RegionCount
	}
	
	Gui, Add, ListView,xm  r%listViewRows% w400 -ReadOnly, Name|Track	
	Loop %RegionCount%
	{
		curRegionName := Region%A_Index%_Name
		LV_Add("", curRegionName, A_Index)
		;Gui, Add, Edit, vTmpRegionName%A_Index% w%inputWidth%, %curRegionName%
	}
	LV_ModifyCol(1, 300)
	LV_ModifyCol(2, 50)
	LV_ModifyCol(2, "Integer")

	Gui, Add, Text,xm r1,Filename Prefix:
	Gui, Add, Edit, vUserVar_FilenamePrefix w%inputWidth% xp+%Col1Width% r1, %UserVar_FilenamePrefix%

	If StrLen( rcButtonQueue ) > 0
	{	
		Gui, Add, Checkbox, vUseRenderQueue x140 Checked%UseRenderQueue%, Use Reaper render queue
	}
	Gui, Add, Checkbox, vNumberOutputFiles x125 Checked%NumberOutputFiles%, Sequentially number output files

	Gui, Add, Text,xm r1 x125, Track number digits (0 for auto) 
	Gui, Add, Edit, w30 r1 xp+150 ReadOnly
	Gui, Add, UpDown, vPadTrackNumber Range0-9

	Gui, Add, Checkbox, vParseArtistFromRegionName x90, Parse artist from region name [Artist - Track Name]

	Gui, Add, Checkbox, vArtistAlbumFolders x130 Checked%ArtistAlbumFolders%, Create artist/album subfolders
	Gui, Add, Checkbox, vZipRenderedFiles x110 Checked%ZipRenderedFiles%, Create a zip file of rendered audio files
	
	
	If (UserVar_ftpSite AND UserVar_ftpUser AND UserVar_ftpPass AND UserVar_ftpDir)
	{
		Gui, Add, Checkbox, vUploadFTP x165, Upload via FTP
	}
	
	Gui, Add, Button,default x150 W50 r1,OK  ; The label ButtonOK (if it exists) will be run when the button is pressed.	
	Gui, Add, Button,x225 yp W50 r1,Cancel


	Gui, Show,,Autorender - Edit Metadata
	Loop
	{
		If Submitted
		{
			Break
		}
		Sleep, 1000
	}
		
	ButtonOK:	
	Gui, Submit  ; Save the input from the user to each control's associated variable.	
	AppendLog("Set metadata variables in GUI", 1)

	UserVarCount++
	
	;write metadata variables to log file
	LogVar := "Artist = " . UserVar_Artist
	AppendLog(LogVar)
	LogVar := "Album = " . UserVar_Album
	AppendLog(LogVar)
	LogVar := "Genre = " . UserVar_Genre
	AppendLog(LogVar)
	LogVar := "Year = " . UserVar_Year
	AppendLog(LogVar)
	LogVar := "Filename Prefix = " . UserVar_filenamePrefix
	AppendLog(LogVar)
	
	Loop %RegionCount%
	{
		;Reset track names
		LV_GetText(curRegionName, A_Index)
		SetRegionName(A_Index, curRegionName)
		
		;Write track names to log file
		LogVar := "Track " . A_Index . " = " . curRegionName
		AppendLog(LogVar)
	}

	autoTrackPad := Floor(Log(RegionCount)) + 1

	if( autoTrackPad = 1 AND PadTrackNumber = 0)
	{
		autoTrackPad := 2
	}

	If( PadTrackNumber < autoTrackPad )
	{
		PadTrackNumber := autoTrackPad	
	}
	
	Submitted = 1
	Return

	GuiEscape:
	GuiClose:
	ButtonCancel:
	Gui, Destroy
	ExitApp
	Return
	
	ButtonBrowse:
	FileSelectFolder, SFolder
	If SFolder != 
	{
		GuiControl,,UserVar_RenderPath, %SFolder%
	}
	Return
}

CheckForUnsavedProject()
{
	global
	
	Loop
	{
		WinGetTitle,ReaperTitle,ahk_id %ReaperID%
		If RegExMatch(ReaperTitle,"\[unsaved project\]")
		{   
			MsgBox,262144,Unsaved project,Please save your new project and re-run Autorender.
			ExitApp
		}
		Else
		{
			Break
		}
	}
	
	Loop
	{
		WinGetTitle,ReaperTitle,ahk_id %ReaperID%
		If RegExMatch(ReaperTitle,"\[modified\]")
		{   
			MsgBox,262209,Save project,Autorender needs to save the project to continue.
			IfMsgBox Ok
			{
				PostMessage,0x111,40026,,,ahk_id %ReaperID%            ;Save
				Sleep 1000*SleepMultiplier
			}
			Else
			{
				ExitApp
			}
		}
		Else
		{
			Break
		}
	}	
}

SetRenderPath()
{
	global	

	Loop
	{		
		If UserVar_RenderPath
		{		
			;===Trim trailing slash from renderPath if present
		    UserVar_RenderPath := RegExReplace(UserVar_RenderPath,"\\$")
		    If FileExist(UserVar_RenderPath)
			{
				RenderPath := UserVar_RenderPath
				Break
			}
		}

		If !RenderPath or !FileExist(RenderPath)
		{
		    ;===Use DefaultRenderPath in Autorender.ini
		    RenderPath := DefaultRenderPath
		}

		If !RenderPath or !FileExist(RenderPath)
		{
		    ;===Ask for RenderPath
		    FileSelectFolder, RenderPath,,,Select Render Output Folder
			If RenderPath =
			{
				ExitApp
			}
		}

		If FileExist(RenderPath)
		{
			Break
		}

		MsgBox,262145,Need output folder,Autorender needs a valid output folder to continue.
		IfMsgBox Cancel
		{
			ExitApp
		}	
	}
	
	originalRenderPath := RenderPath
	
	;now that render path has been verified, see if we need to create album/artist subfolders	
	If ArtistAlbumFolders
	{
		If UserVar_Artist
		{
			RenderPath = %RenderPath%\%UserVar_Artist%
		}
		Else
		{
			RenderPath = %RenderPath%\Unknown Artist
		}

		If UserVar_Album
		{
			RenderPath = %RenderPath%\%UserVar_Album%
		}
		Else
		{
			RenderPath = %RenderPath%\Unknown Album
		}
		
		If !FileExist(RenderPath)
		{
			FileCreateDir, %RenderPath%
		}
	}
}

StoreRenderPath()
{
	global
	IniWrite, %RenderPath%, Autorender.ini, Autorender, LastRenderPath
}

KeepMediaItemsOnline()
{
	global	
	;=== Set preference to keep media items online when application is not active, but remember previous user setting
	WinActivate,ahk_id %ReaperID%
	WinWaitActive,ahk_id %ReaperID%
	PostMessage,0x111,40016,,,ahk_id %ReaperID%			;Open preferences window
	WinWait,REAPER Preferences
	WinActivate,REAPER Preferences
	WinWaitActive,REAPER Preferences	

	ControlSettext,Edit1,media offline
	ControlClick,Button1
	Sleep,200		
	
	Loop
	{
		ControlGet,remOfflineMediaWhenInactive,Checked,,Set media items offline
		If remOfflineMediaWhenInactive =
		{
			;Send,m
			ControlSettext,Edit1,media offline
			ControlClick,Button1
			Sleep,200		
		}
		Else
		{
			Sleep,200
			Break
		}
	}

	Control,Uncheck,,Set media items offline
	PostMessage,0x111,1,,,REAPER Preferences			;Say ok
	AppendLog("User's offline media preference: " . remOfflineMediaWhenInactive)
	Return remOfflineMediaWhenInactive	
}

SetMediaItemsOffline()
{
	global ReaperID
	;=== Change media offline preference back to user's
	WinActivate,ahk_id %ReaperID%
	WinWaitActive,ahk_id %ReaperID%
	PostMessage,0x111,40016,,,ahk_id %ReaperID%			;Open preferences window
	WinWait,REAPER Preferences
	WinActivate,REAPER Preferences
	WinWaitActive,REAPER Preferences	

	ControlSettext,Edit1,Set media items offline
	ControlClick,Button1

	Loop
	{
		ControlGet,didWeGetOfflineSetting,Checked,,Set media items offline
		If didWeGetOfflineSetting =
		{
			Send,m
			Sleep,100		
		}
		Else
		{
			Break	
		}
	}
	
	Control,Check,,Set media items offline
	PostMessage,0x111,1,,,REAPER Preferences			;Say ok
	AppendLog("Set media items to go offline when Reaper loses focus (user's preference)")
}

LoadCurrentRegionVars( RegionNumber )
{
	global
	local dashPos, tempTrackName 
	
	thisRegionName := Region%RegionNumber%_Name
	thisFixedRegionName := Region%RegionNumber%_Filename
	thisRegionFilename = %thisFixedRegionName%.%renderFormatExt%		
	
	thisTrackNumber := StrPad( firstTrack + RegionNumber - 1, PadTrackNumber )

	thisRegionStartRaw := Region%RegionNumber%_StartTime
	thisRegionEndRaw := Region%RegionNumber%_EndTime

	thisRegionStart := Region%RegionNumber%_StartTimeMinSec
	thisRegionEnd := Region%RegionNumber%_EndTimeMinSec
	
	If (RenderEntire Or !NumberOutputFiles)
	{			
		thisRegionListing = %thisRegionName%
	}
	Else
	{
		thisRegionFilename = %thisTrackNumber% - %thisRegionFilename%
		thisRegionListing = %thisTrackNumber% - %thisRegionName%
	}	

	If UserVar_filenamePrefix !=
	{
		thisRegionFilename = %UserVar_filenamePrefix% - %thisRegionFilename%
	}		
	
	thisRegionFullPath = %renderPath%\%thisRegionFilename%

	If ArtistAlbumFolders
	{
		thisTrackURL = http://%UserVar_ftpUrl%/%createArtistDir%/%createAlbumDir%/%thisRegionFilename%
	}
	Else
	{
		thisTrackURL = http://%UserVar_ftpUrl%/%thisRegionFilename%
	}
	
	If ParseArtistFromRegionName
	{
		dashPos := InStr(thisRegionName,"-")
		If dashPos
		{
			thisTrackArtist := SubStr( thisRegionName, 1, dashPos - 1 )
			thisTrackArtist = %thisTrackArtist%
			
			thisRegionName := SubStr( thisRegionName, (dashPos + 1) )
			thisRegionName = %thisRegionName%			
		}
		Else 
		{
			thisTrackArtist = Unknown Artist
		}	
		
	}	
}


InitIniFile()
{

	global

	;===MAIN SECTION
	
	IniRead, UserVar_renderPath, Autorender.ini, Autorender, DefaultRenderPath
	If UserVar_renderPath = ERROR
	{
		UserVar_renderPath := ""
		IniWrite, %UserVar_renderPath%, Autorender.ini, Autorender, DefaultRenderPath
		UserVar_renderPath =
	}

	IniRead, UserVar_lastRenderPath, Autorender.ini, Autorender, LastRenderPath
	If UserVar_lastRenderPath = ERROR
	{
		UserVar_lastRenderPath := ""
		IniWrite, %UserVar_lastRenderPath%, Autorender.ini, Autorender, LastRenderPath
		UserVar_lastRenderPath =
	}

	If UserVar_renderPath =
	{
		UserVar_renderPath := UserVar_lastRenderPath
	}

	IniRead, RenderCompleteSound, Autorender.ini, Autorender, RenderCompleteSound
	If RenderCompleteSound = ERROR
	{
		RenderCompleteSound = %A_Windir%\Media\notify.wav
		IniWrite, %RenderCompleteSound%, Autorender.ini, Autorender, RenderCompleteSound
	}

	IniRead, SleepMultiplier, Autorender.ini, Autorender, SleepMultiplier
	If SleepMultiplier = ERROR
	{
		SleepMultiplier = 1
		IniWrite, %SleepMultiplier%, Autorender.ini, Autorender, SleepMultiplier
	}

	IniRead, NumberOutputFiles, Autorender.ini, Autorender, NumberOutputFiles
	If NumberOutputFiles = ERROR
	{
		NumberOutputFiles = 1
		IniWrite, %NumberOutputFiles%, Autorender.ini, Autorender, NumberOutputFiles
	}

	IniRead, ArtistAlbumFolders, Autorender.ini, Autorender, ArtistAlbumFolders
	If ArtistAlbumFolders = ERROR
	{
		ArtistAlbumFolders = 0
		IniWrite, %ArtistAlbumFolders%, Autorender.ini, Autorender, ArtistAlbumFolders
	}
	IniRead, ZipRenderedFiles, Autorender.ini, Autorender, ZipRenderedFiles
	If ZipRenderedFiles = ERROR
	{
		ZipRenderedFiles = 0
		IniWrite, %ZipRenderedFiles%, Autorender.ini, Autorender, ZipRenderedFiles
	}


	;===FTP

	IniRead, UserVar_ftpSite, Autorender.ini, FTP, ftpSite
	If UserVar_ftpSite = ERROR
	{
		UserVar_ftpSite := ""
		IniWrite, %UserVar_ftpSite%, Autorender.ini, FTP, ftpSite
		UserVar_ftpSite =
	}

	IniRead, UserVar_ftpUser, Autorender.ini, FTP, ftpUsername
	If UserVar_ftpUser = ERROR
	{
		UserVar_ftpUser := ""
		IniWrite, %UserVar_ftpUser%, Autorender.ini, FTP, ftpUsername
		UserVar_ftpUser =
	}

	IniRead, UserVar_ftpPass, Autorender.ini, FTP, ftpPassword
	If UserVar_ftpPass = ERROR
	{
		UserVar_ftpPass := ""
		IniWrite, %UserVar_ftpPass%, Autorender.ini, FTP, ftpPassword
		UserVar_ftpPass =
	}

	IniRead, UserVar_ftpDir, Autorender.ini, FTP, ftpDirectory
	If UserVar_ftpDir = ERROR
	{
		UserVar_ftpDir := ""
		IniWrite, %UserVar_ftpDir%, Autorender.ini, FTP, ftpDirectory
		UserVar_ftpDir =
	}

	IniRead, UserVar_ftpUrl, Autorender.ini, FTP, ftpUrl
	If UserVar_ftpUrl = ERROR
	{
		UserVar_ftpUrl := ""
		IniWrite, %UserVar_ftpUrl%, Autorender.ini, FTP, ftpUrl
		UserVar_ftpUrl =
	}
}

LogCompyStats()
{
AppendLog("SYSTEM STATS",1)
AppendLog("OS Type: " . A_OSType)
AppendLog("OS Version: " . A_OSVersion)
AppendLog("Language: " . A_Language)
AppendLog("Admin: " . A_IsAdmin)
}

GetCurrentPos()
{
	global ReaperID
	
	PostMessage,0x111,40069,,,ahk_id %ReaperID%            ;Open jump dialog
	WinWait,Jump
	ControlGetText,curPos,Edit1
	WinWaitClose,Jump
	WinWait,ahk_id %ReaperID%
	Return curPos
}

AutoGenerateRegions()
{
	global ReaperID, HumanEditTrackNames
	
	;Go to start:  40042
	;Select/move to next item: 40417	
	;Select move to previous item: 40416	
	;Set time selection to selected items: 40290	
	;Delete region near cursor: 40615	
	;Insert region from time selection: 40174	
	;Edit region near cursor: 40616	
	;Select and move to next item: 40417
	;Select and move to next item: 40417

	Sleeper = 50
	
	NumItems := GetNumberOfItems()
	
	;DELETE REGIONS
	Loop %NumItems%
	{
		If A_Index = 1
		{
			;First item
			PostMessage,0x111,40042,,,ahk_id %ReaperID%		;Go to start
			Sleep, %Sleeper%
			PostMessage,0x111,40417,,,ahk_id %ReaperID%		;Select and move to next item
			Sleep, %Sleeper%
			PostMessage,0x111,40416,,,ahk_id %ReaperID%		;Select and move to previous item
			Sleep, %Sleeper%		
		}
		Else
		{
			PostMessage,0x111,40417,,,ahk_id %ReaperID%		;Select and move to next item
			Sleep, %Sleeper%		
		}
		
		PostMessage,0x111,40615,,,ahk_id %ReaperID%		;Delete region near cursor
		Sleep, %Sleeper%
	}	
	
	;MAKE NEW REGIONS
	Loop %NumItems%
	{
		If A_Index = 1
		{
			;First item
			PostMessage,0x111,40042,,,ahk_id %ReaperID%		;Go to start
			Sleep, %Sleeper%
			PostMessage,0x111,40417,,,ahk_id %ReaperID%		;Select and move to next item
			Sleep, %Sleeper%
			PostMessage,0x111,40416,,,ahk_id %ReaperID%		;Select and move to previous item
			Sleep, %Sleeper%		
		}
		Else
		{
			PostMessage,0x111,40417,,,ahk_id %ReaperID%		;Select and move to next item
			Sleep, %Sleeper%		
		}
				
		PostMessage,0x111,40290,,,ahk_id %ReaperID%		;Set time selection to selected items
		Sleep, %Sleeper%
		;PostMessage,0x111,40615,,,ahk_id %ReaperID%		;Delete region near cursor
		;Sleep, %Sleeper%
		
		PostMessage,0x111,40174,,,ahk_id %ReaperID%		;Insert region from time selection
		Sleep, %Sleeper%
		
		CurrentItemName := GetCurrentItemName()
		PostMessage,0x111,40616,,,ahk_id %ReaperID%		;Edit region near cursor
		WinWait,Edit Region
		If HumanEditTrackNames
		{
			WinWaitActive
			WinWaitClose
		}
		Else
		{
			WinWait,Edit Region
			ControlSetText,Edit1,%CurrentItemName%
			ControlClick,Button1
			WinWaitClose
		}
		
	}	 

	PostMessage,0x111,40289,,,ahk_id %ReaperID%		;Unselect all items
	PostMessage,0x111,40635,,,ahk_id %ReaperID%		;Remove time selection	
	PostMessage,0x111,40042,,,ahk_id %ReaperID%		;Go to start
	

}

GetCurrentItemName()
{
	global ReaperID
	
	PostMessage,0x111,40009,,,ahk_id %ReaperID%            ;Open item properties dialog
	WinWait,Media Item Properties
	ControlGetText,curItemName,Edit6
	curItemName := RegExReplace( curItemName, "(.*)\..*$", "$1" ) ;get rid of extension if there is one
	curItemName := RegExReplace( curItemName, "^\d{1,3}\s*-?\s*(.*)$", "$1" ) ;get rid of track number	
	WinKill
	Return curItemName
}

GetNumberOfItems()
{
	global ReaperID

	;Select all items in selected tracks
	PostMessage,0x111,40421,,,ahk_id %ReaperID%		;Select all items in selected tracks	
	PostMessage,0x111,40009,,,ahk_id %ReaperID%		;View Properties Dialog

	StartSearch := A_TickCount
	Loop
	{
		IfWinExist, Media Item Properties
		{
			NumItems = 1
			WinKill
			Break
		}
		Else IfWinExist, Multiple Item Properties
		{	
			ControlGetText, MultipleItemText, Static1 ;Get multiple item warning
			NumItems := RegExReplace( MultipleItemText, "^[^\d]*([\d]*)[^\d]*$", "$1" )
			WinKill
			Break
		}
		Else If A_TickCount - StartSearch > 3000
		{
			MsgBox,262193,Couldn't find items,Could not get media items. Make sure a track is selected and try again.
			IfMsgbox OK
			{
				PostMessage,0x111,40421,,,ahk_id %ReaperID%		;Select all items in selected tracks	
				PostMessage,0x111,40009,,,ahk_id %ReaperID%		;View Properties Dialog
				StartSearch := A_TickCount			
			}
			Else
			{
				ExitApp
			}
		}
	}
	
	Return NumItems
}